package analisadorsemantico;

import analisadorlexico.Token;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.Map;

public class AnalisadorSemantico {

    private Token token;
    private LinkedList<Token> listaToken; // lista de estados de aceitacao
    private LinkedList<String> listaErro;
    private Hashtable<String, Constante> constante = new Hashtable<String, Constante>();
    private Hashtable<String, Variavel> varGlobais = new Hashtable<String, Variavel>();
    private Hashtable registros = new Hashtable();
    private Hashtable<String, Funcao> funcoes = new Hashtable<String, Funcao>();
    	    private Map<String, Registro> registro = new Hashtable<String, Registro>();

 
       
            
            
            public AnalisadorSemantico(LinkedList<Token> listaToken) {
        setListaToken(listaToken);
        listaErro = new LinkedList<>();
    }
            
            
            

    public Hashtable<String, Variavel> getVarGlobal() {
        return varGlobais;
    }

    public void setVarGlobal(Hashtable<String, Variavel> varGlobal) {
        this.varGlobais = varGlobal;
    }

    public Hashtable<String, Constante> getConstante() {
        return constante;
    }

    public void setConstante(Hashtable<String, Constante> constante) {
        this.constante = constante;
    }

    public LinkedList<String> getListaErro() {
        return listaErro;
    }

    public void setListaErro(LinkedList<String> listaErro) {
        this.listaErro = listaErro;
    }
    private String aux;



    public Token getToken() {
        return token;
    }

    public void setToken(Token token) {
        this.token = token;
    }

    public LinkedList<Token> getListaToken() {
        return listaToken;
    }

    public final void setListaToken(LinkedList<Token> listaToken) {
        this.listaToken = listaToken;
        this.listaToken.add(new Token("$", "fim", 400)); // adicionando $ ao fim do arquivo
    }

    // método proximo_token 
    // observacao metodos iguais ao da gramatica
    public void proximo_token() {
        if (!listaToken.isEmpty()) {
            token = listaToken.getFirst();
            listaToken.removeFirst();
            System.out.println("Token: " + token.getLexema());
        }
    }

    public void sintatico() {
        proximo_token();
        if (token.getLexema().equals("program")) {
            proximo_token();
            if (token.getTipo().equals("Identificador")) {
                proximo_token();
                if (token.getLexema().equals(";")) {
                    proximo_token();
                    declara_constante();
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou ;");
                    aux = ("Linha: " + token.getLinha() + " - Faltou ;");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case ";":
                                teste = false;
                                proximo_token();
                                declara_constante();
                                break;
                            case "const":
                                teste = false;
                                declara_constante();
                                break;
                            case "var":
                                teste = false;
                                declara_constante();
                                break;
                            case "type":
                                teste = false;
                                declara_registro();
                                break;
                            case "function":
                                teste = false;
                                declara_constante();
                                break;
                            case "main":
                                teste = false;
                                declara_constante();
                                break;
                            default:
                                proximo_token();
                        }
                    }
                }
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou nome do programa");
                aux = ("Linha: " + token.getLinha() + " - Faltou nome do programa");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case ";":
                            teste = false;
                            proximo_token();
                            declara_constante();
                            break;
                        case "const":
                            teste = false;
                            declara_constante();
                            break;
                        case "var":
                            teste = false;
                            declara_constante();
                            break;
                        case "type":
                            teste = false;
                            declara_registro();
                            break;
                        case "function":
                            teste = false;
                            declara_constante();
                            break;
                        case "main":
                            teste = false;
                            declara_constante();
                            break;
                        default:
                            proximo_token();
                    }
                }
            }
        } else {
            aux = "Linha: " + token.getLinha() + " - Faltou program";
            System.out.println(aux);
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case ";":
                        teste = false;
                        proximo_token();
                        declara_constante();
                        break;
                    case "const":
                        teste = false;
                        declara_constante();
                        break;
                    case "var":
                        teste = false;
                        declara_constante();
                        break;
                    case "type":
                        teste = false;
                        declara_registro();
                        break;
                    case "function":
                        teste = false;
                        declara_constante();
                        break;
                    case "main":
                        teste = false;
                        declara_constante();
                        break;
                    default:
                        proximo_token();
                }
            }
        }
    }

    public void declara_constante() {
        if (token.getLexema().equals("const")) {
            proximo_token();
            if (token.getLexema().equals("{")) {
                proximo_token();
                bloco_constante();
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou {");
                aux = ("Linha: " + token.getLinha() + " - Faltou {");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "}":
                            teste = false;
                            proximo_token();
                            declara_var_global();
                            break;
                        case "var":
                            teste = false;
                            declara_var_global();
                            break;
                        case "type":
                            teste = false;
                            declara_registro();
                            break;
                        case "function":
                            teste = false;
                            declara_var_global();
                            break;
                        case "main":
                            teste = false;
                            declara_var_global();
                            break;
                        case "integer":
                        case "real":
                        case "boolean":
                        case "string":
                        case "char":
                            teste = false;
                            bloco_constante();
                            break;
                        default:
                            proximo_token();
                    }
                }
            }
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou const");
            aux = ("Linha: " + token.getLinha() + " - Faltou const");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case "{":
                        teste = false;
                        proximo_token();
                        bloco_constante();
                        break;
                    case "var":
                        teste = false;
                        declara_var_global();
                        break;
                    case "type":
                        teste = false;
                        declara_registro();
                        break;
                    case "function":
                        teste = false;
                        declara_var_global();
                        break;
                    case "main":
                        teste = false;
                        declara_var_global();
                        break;
                    default:
                        proximo_token();
                }
            }
        }
    }

    public void identificador() {
        if (token.getTipo().equals("Identificador")) {
            proximo_token();
            identificador_vetor();
        } else {
        }
    }

    public void identificador_vetor() {
        switch (token.getLexema()) {
            case "[":
                proximo_token();
                indice_vetor_matriz();
                if (token.getLexema().equals("]")) {
                    proximo_token();
                    identificador_matriz();
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou ]");
                    aux = ("Linha: " + token.getLinha() + " - Faltou ]");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case ";":
                                teste = false;
                                proximo_token();
                                break;
                            case "}":
                                teste = false;
                                break;
                            default:
                                proximo_token();
                        }
                    }
                }
                break;
            case ";":
                proximo_token();
                break;
            default:
                System.out.println("Linha: " + token.getLinha() + " - Faltou ;");
                aux = ("Linha: " + token.getLinha() + " - Faltou ;");
                listaErro.add(aux);
                break;
        }
    }

    public void identificador_matriz() {
        switch (token.getLexema()) {
            case "[":
                proximo_token();
                indice_vetor_matriz();
                if (token.getLexema().equals("]")) {
                    proximo_token();
                    if (token.getLexema().equals(";")) {
                        proximo_token();
                    } else {
                        System.out.println("Linha: " + token.getLinha() + " - Faltou ;");
                        aux = ("Linha: " + token.getLinha() + " - Faltou ;");
                        listaErro.add(aux);
                    }
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou ]");
                    aux = ("Linha: " + token.getLinha() + " - Faltou ]");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case ";":
                                teste = false;
                                proximo_token();
                                break;
                            case "}":
                                teste = false;
                                break;
                            default:
                                proximo_token();
                        }
                    }
                }
                break;
            case ";":
                proximo_token();
                break;
            default:
                System.out.println("Linha: " + token.getLinha() + " - Faltou ;");
                aux = ("Linha: " + token.getLinha() + " - Faltou ;");
                listaErro.add(aux);
                break;
        }
    }

    public void identificador2() {
        if (token.getTipo().equals("Identificador")) {
            proximo_token();
            identificador_vetor2();
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou identificador");
            aux = ("Linha: " + token.getLinha() + " - Faltou identificador");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case ",":
                        teste = false;
                        break;
                    case ")":
                        teste = false;
                        break;
                    default:
                        proximo_token();
                }
            }
        }
    }

    public void identificador_vetor2() {
        switch (token.getLexema()) {
            case "[":
                proximo_token();
                indice_vetor_matriz();
                if (token.getLexema().equals("]")) {
                    proximo_token();
                    identificador_matriz2();
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou ]");
                    aux = ("Linha: " + token.getLinha() + " - Faltou ]");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case ",":
                                teste = false;
                                break;
                            case ")":
                                teste = false;
                                break;
                            default:
                                proximo_token();
                        }
                    }
                }
                break;
            default:
                break;
        }
    }

    public void identificador_matriz2() {
        switch (token.getLexema()) {
            case "[":
                proximo_token();
                indice_vetor_matriz();
                if (token.getLexema().equals("]")) {
                    proximo_token();
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou ]");
                    aux = ("Linha: " + token.getLinha() + " - Faltou ]");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case ",":
                                teste = false;
                                break;
                            case ")":
                                teste = false;
                                break;
                            default:
                                proximo_token();
                        }
                    }
                }
                break;
            default:
                break;
        }
    }

    public void indice_vetor_matriz() {
        switch (token.getTipo()) {
            case "Identificador":
            case "Numero":
                proximo_token();
                break;
            default:
                System.out.println("Linha: " + token.getLinha() + " - Erro no indice de acesso");
                aux = ("Linha: " + token.getLinha() + " - Erro no indice de acesso");
                listaErro.add(aux);
        }
    }

    public void identificador_vetor_registro() {
        if (token.getTipo().equals("Identificador")) {
            proximo_token();
            identificador_continua();
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou identificador");
            aux = ("Linha: " + token.getLinha() + " - Faltou identificador");
            listaErro.add(aux);
        }
    }

    public void identificador_continua() {
        switch (token.getLexema()) {
            case ".":
                proximo_token();
                if (token.getTipo().equals("Identificador")) {
                    proximo_token();
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou campo do registro");
                    aux = ("Linha: " + token.getLinha() + " - Faltou campo do registro");
                    listaErro.add(aux);
                }
                break;
            case "[":
                proximo_token();
                indice_vetor_matriz();
                if (token.getLexema().equals("]")) {
                    proximo_token();
                    identificador_matriz2();
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou ]");
                    aux = ("Linha: " + token.getLinha() + " - Faltou ]");
                    listaErro.add(aux);
                }
                break;
            default:
                break;
        }
    }

    public void declara_funcao() {
        if (token.getLexema().equals("function")) {
            Funcao funcao = new Funcao();
            boolean flagErro = false;
            proximo_token();
            switch (token.getLexema()) {
                case "void":
                case "integer":
                case "real":
                case "boolean":
                case "strng":
                case "char":
                    funcao.setTipoRetorno(token.getLexema());
                    proximo_token();
                    break;
                default:
                    if (token.getTipo().equals("Identificador") && registros.containsKey(token.getLexema())) {
                        funcao.setTipoRetorno(token.getLexema());
                        proximo_token();
                    } else {
                        proximo_token();
                        flagErro = true;
                        System.out.println("ERRO");
                    }
                    break;
            }
            if (token.getTipo().equals("Identificador")) {
                funcao.setNome(token.getLexema());
                proximo_token();
            } else {
                flagErro = true;
                proximo_token();
            }
            if (token.getLexema().equals("(")) {
                proximo_token();
                while (!token.getLexema().equals(")")) {
                    Variavel var = new Variavel();
                    switch (token.getLexema()) {
                        case "integer":
                        case "real":
                        case "boolean":
                        case "strng":
                        case "char":
                            var.setTipo(token.getLexema());
                            proximo_token();
                            break;
                        default:
                            if (token.getTipo().equals("Identificador") && registros.containsKey(token.getLexema())) {
                                var.setTipo(token.getLexema());
                                proximo_token();
                                if(token.getLexema().equals(",")){
                                    funcao.getParametro().put(var.getIdentificador(), var);
                                }                                                        
                            } else {
                                proximo_token();
                                flagErro = true;
                                System.out.println("ERRO");
                            }
                            break;
                    }
                    if(token.getTipo().equals("Identificador")){
                        var.setIdentificador(token.getLexema());
                        proximo_token();
                    }
                }
                proximo_token();
                if (token.getLexema().equals("{")) {
                    proximo_token();
                    declara_var_local();
                } else {
                }



            }
        } else {
            declara_main();
        }
    }

    public void tipo_extendido() {
        if (token.getTipo().equals("Identificador")) {
            proximo_token();
        } else {
            tipo_primitivo();
        }
    }

    public void tipo_retorno() {
        if (token.getLexema().equals("void")) {
            proximo_token();
        } else {
            tipo_extendido();
        }
    }

    public void parametros() {
        if (token.getLexema().equals(")")) {
            proximo_token();
            if (token.getLexema().equals("{")) {
                proximo_token();
                declara_var_local();
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou {");
                aux = ("Linha: " + token.getLinha() + " - Faltou {");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "var":
                            teste = false;
                            declara_var_local();
                            break;
                        case "main":
                            teste = false;
                            declara_main();
                            break;
                        case "function":
                            teste = false;
                            declara_funcao();
                            break;
                        default:
                            proximo_token();
                    }
                }
            }
        } else {
            lista_parametros();
        }
    }

    public void lista_parametros() {
        if (token.getTipo().equals("Identificador") || token.getLexema().equals("integer") || token.getLexema().equals("real") || token.getLexema().equals("boolean") || token.getLexema().equals("string") || token.getLexema().equals("char")) {
            tipo_extendido();
            if (token.getTipo().equals("Identificador")) {
                identificador2();
                complemento_parametro();
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou o nome do parametro");
                aux = ("Linha: " + token.getLinha() + " - Faltou o nome do parametro");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case ",":
                            teste = false;
                            complemento_parametro();
                            break;
                        case ")":
                            teste = false;
                            complemento_parametro();
                            break;
                        case "{":
                            teste = false;
                            proximo_token();
                            declara_var_local();
                            break;
                        case "var":
                            teste = false;
                            declara_var_local();
                            break;
                        case "main":
                            teste = false;
                            declara_main();
                            break;
                        case "function":
                            teste = false;
                            declara_funcao();
                            break;
                        default:
                            proximo_token();
                    }
                }
            }
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou tipo do parametro");
            aux = ("Linha: " + token.getLinha() + " - Faltou tipo do parametro");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case ",":
                        teste = false;
                        complemento_parametro();
                        break;
                    case ")":
                        teste = false;
                        complemento_parametro();
                        break;
                    case "{":
                        teste = false;
                        proximo_token();
                        declara_var_local();
                        break;
                    case "var":
                        teste = false;
                        declara_var_local();
                        break;
                    case "main":
                        teste = false;
                        declara_main();
                        break;
                    case "function":
                        teste = false;
                        declara_funcao();
                        break;
                    default:
                        proximo_token();
                }
            }
        }
    }

    public void complemento_parametro() {
        switch (token.getLexema()) {
            case ",":
                proximo_token();
                lista_parametros();
                break;
            case ")":
                proximo_token();
                if (token.getLexema().equals("{")) {
                    proximo_token();
                    declara_var_local();
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou {");
                    aux = ("Linha: " + token.getLinha() + " - Faltou {");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case "var":
                                teste = false;
                                declara_var_local();
                                break;
                            case "main":
                                teste = false;
                                declara_main();
                                break;
                            case "function":
                                teste = false;
                                declara_funcao();
                                break;
                            default:
                                proximo_token();
                        }
                    }
                }
                break;
            default:
                System.out.println("Linha: " + token.getLinha() + " - Faltou )");
                aux = ("Linha: " + token.getLinha() + " - Faltou )");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "{":
                            teste = false;
                            proximo_token();
                            declara_var_local();
                            break;
                        case "var":
                            teste = false;
                            declara_var_local();
                            break;
                        case "main":
                            teste = false;
                            declara_main();
                            break;
                        case "function":
                            teste = false;
                            declara_funcao();
                            break;
                        default:
                            proximo_token();
                    }
                }
                break;
        }
    }

    public void corpo_funcao() {
        if (token.getLexema().equals("if") || token.getLexema().equals("for") || token.getLexema().equals("while") || token.getLexema().equals("read") || token.getLexema().equals("write")) {
            comandos();
            corpo_funcao();
        } else if (token.getLexema().equals("function")) {
            chama_funcao();
            corpo_funcao();
        } else if (token.getLexema().equals("++") || token.getLexema().equals("--") || token.getTipo().equals("Identificador")) {
            atribuicao();
            corpo_funcao();
        } else if (token.getLexema().equals("return")) {
            proximo_token();
            finaliza_funcao();
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Operação invalida");
            aux = "Linha: " + token.getLinha() + " - Operação invalida";
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case "if":
                    case "for":
                    case "while":
                    case "read":
                    case "write":
                        teste = false;
                        comandos();
                        corpo_funcao();
                        break;
                    case "function":
                        teste = false;
                        chama_funcao();
                        corpo_funcao();
                        break;
                    case "++":
                    case "--":
                        teste = false;
                        atribuicao();
                        corpo_funcao();
                        break;
                    case "return":
                        teste = false;
                        proximo_token();
                        finaliza_funcao();
                        break;
                    default:
                        if (token.getTipo().equals("Identificador")) {
                            teste = false;
                            atribuicao();
                            corpo_funcao();
                            break;
                        } else {
                            proximo_token();
                        }

                }
            }
        }
    }

    public void finaliza_funcao() {
        if (token.getTipo().equals("Identificador")) {
            identificador_vetor_registro();
            if (token.getLexema().equals(";")) {
                proximo_token();
                if (token.getLexema().equals("}")) {
                    proximo_token();
                    declara_funcao();
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou }");
                    aux = ("Linha: " + token.getLinha() + " - Faltou }");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "function":
                                teste = false;
                                declara_funcao();
                                break;
                            case "main":
                                teste = false;
                                declara_main();
                                break;
                            default:
                                proximo_token();
                        }
                    }
                }
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou ;");
                aux = ("Linha: " + token.getLinha() + " - Faltou ;");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "}":
                            teste = false;
                            proximo_token();
                            declara_funcao();
                            break;
                        case "function":
                            teste = false;
                            declara_funcao();
                            break;
                        case "main":
                            teste = false;
                            declara_main();
                            break;
                        default:
                            proximo_token();
                    }
                }
            }
        } else if (token.getTipo().equals("Numero") || token.getTipo().equals("Numero real") || token.getTipo().equals("Caracter") || token.getTipo().equals("String") || token.getLexema().equals("true") || token.getLexema().equals("false")) {
            valor();
            if (token.getLexema().equals(";")) {
                proximo_token();
                if (token.getLexema().equals("}")) {
                    proximo_token();
                    declara_funcao();
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou }");
                    aux = ("Linha: " + token.getLinha() + " - Faltou }");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case "function":
                                teste = false;
                                declara_funcao();
                                break;
                            case "main":
                                teste = false;
                                declara_main();
                                break;
                            default:
                                proximo_token();
                        }
                    }
                }
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou ;");
                aux = ("Linha: " + token.getLinha() + " - Faltou ;");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "}":
                            teste = false;
                            proximo_token();
                            declara_funcao();
                            break;
                        case "function":
                            teste = false;
                            declara_funcao();
                            break;
                        case "main":
                            teste = false;
                            declara_main();
                            break;
                        default:
                            proximo_token();
                    }
                }
            }
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou valor do retorno");
            aux = ("Linha: " + token.getLinha() + " - Faltou valor do retorno");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case "}":
                        teste = false;
                        proximo_token();
                        declara_funcao();
                        break;
                    case "function":
                        teste = false;
                        declara_funcao();
                        break;
                    case "main":
                        teste = false;
                        declara_main();
                        break;
                    default:
                        proximo_token();
                }
            }
        }
    }

    public void comandos() {
        switch (token.getLexema()) {
            case "if":
                proximo_token();
                comando_if();
                break;
            case "for":
                proximo_token();
                comando_for();
                break;
            case "while":
                proximo_token();
                comando_while();
                break;
            case "read":
                proximo_token();
                ler_variavel();
                break;
            case "write":
                proximo_token();
                escreve_tela();
                break;
            default:
                System.out.println("Linha: " + token.getLinha() + " - Comando invalido");
                aux = ("Linha: " + token.getLinha() + " - Comando invalido");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "if":
                        case "for":
                        case "while":
                        case "read":
                        case "write":
                            teste = false;
                            comandos();
                            corpo_funcao();
                            break;
                        case "function":
                            teste = false;
                            chama_funcao();
                            corpo_funcao();
                            break;
                        case "++":
                        case "--":
                            teste = false;
                            atribuicao();
                            corpo_funcao();
                            break;
                        case "return":
                            teste = false;
                            proximo_token();
                            finaliza_funcao();
                            break;
                        default:
                            if (token.getTipo().equals("Identificador")) {
                                teste = false;
                                atribuicao();
                                corpo_funcao();
                                break;
                            } else {
                                proximo_token();
                            }

                    }
                }
                break;
        }
    }

    public void declara_main() {
        if (token.getLexema().equals("main")) {
            proximo_token();
            if (token.getLexema().equals("{")) {
                proximo_token();
                declara_var_local_main();
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou {");
                aux = ("Linha: " + token.getLinha() + " - Faltou {");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "var":
                            teste = false;
                            declara_var_local_main();
                            break;
                        case "if":
                        case "for":
                        case "while":
                        case "write":
                        case "read":
                        case "function":
                            teste = false;
                            corpo_main();
                            break;
                        default:
                            if (token.getTipo().equals("Identificador")) {
                                teste = false;
                                corpo_main();
                            } else {
                                proximo_token();
                            }
                    }
                }
            }
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou main");
            aux = ("Linha: " + token.getLinha() + " - Faltou main");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case "var":
                        teste = false;
                        declara_var_local_main();
                        break;
                    case "if":
                    case "for":
                    case "while":
                    case "write":
                    case "read":
                    case "function":
                        teste = false;
                        corpo_main();
                        break;
                    default:
                        if (token.getTipo().equals("Identificador")) {
                            teste = false;
                            corpo_main();
                        } else {
                            proximo_token();
                        }
                }
            }
        }
    }

    public void declara_var_local_main() {
        if (token.getLexema().equals("var")) {
            proximo_token();
            if (token.getLexema().equals("{")) {
                proximo_token();
                bloco_variaveis_locais_main();
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou {");
                aux = ("Linha: " + token.getLinha() + " - Faltou {");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "if":
                        case "for":
                        case "while":
                        case "write":
                        case "read":
                        case "function":
                            teste = false;
                            corpo_main();
                            break;
                        default:
                            if (token.getTipo().equals("Identificador")) {
                                teste = false;
                                corpo_main();
                            } else {
                                proximo_token();
                            }
                    }
                }
            }
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou var");
            aux = ("Linha: " + token.getLinha() + " - Faltou var");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case "{":
                        teste = false;
                        proximo_token();
                        bloco_variaveis_locais_main();
                        break;
                    case "if":
                    case "for":
                    case "while":
                    case "write":
                    case "read":
                    case "function":
                        teste = false;
                        corpo_main();
                        break;
                    default:
                        if (token.getTipo().equals("Identificador")) {
                            teste = false;
                            corpo_main();
                        } else {
                            proximo_token();
                        }
                }
            }
        }
    }

    public void bloco_variaveis_locais_main() {
        if (token.getTipo().equals("Identificador") || token.getLexema().equals("integer") || token.getLexema().equals("real") || token.getLexema().equals("boolean") || token.getLexema().equals("string") || token.getLexema().equals("char")) {
            tipo_extendido();
            if (token.getTipo().equals("Identificador")) {
                identificador();
                bloco_variaveis_locais_main();
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou nome da variavel");
                aux = ("Linha: " + token.getLinha() + " - Faltou nome da variavel");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case ";":
                            teste = false;
                            proximo_token();
                            bloco_variaveis_locais_main();
                            break;
                        case "}":
                            teste = false;
                            proximo_token();
                            corpo_main();
                            break;
                        case "if":
                        case "for":
                        case "while":
                        case "write":
                        case "read":
                        case "function":
                            teste = false;
                            corpo_main();
                            break;
                        default:
                            if (token.getTipo().equals("Identificador")) {
                                teste = false;
                                corpo_main();
                            } else {
                                proximo_token();
                            }
                    }
                }
            }
        } else if (token.getLexema().equals("}")) {
            proximo_token();
            corpo_main();
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou }");
            aux = ("Linha: " + token.getLinha() + " - Faltou }");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case ";":
                        teste = false;
                        proximo_token();
                        corpo_main();
                        break;
                    case "}":
                        teste = false;
                        proximo_token();
                        break;

                    default:
                        proximo_token();
                }
            }

        }
    }

    public void corpo_main() {
        if (token.getLexema().equals("if") || token.getLexema().equals("for") || token.getLexema().equals("while") || token.getLexema().equals("read") || token.getLexema().equals("write")) {
            comandos();
            corpo_main();
        } else if (token.getLexema().equals("function")) {
            chama_funcao();
            corpo_main();
        } else if (token.getLexema().equals("++") || token.getLexema().equals("--") || token.getTipo().equals("Identificador")) {
            atribuicao();
            corpo_main();
        } else if (token.getLexema().equals("}")) {
            proximo_token();
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Operação invalida");
            aux = ("Linha: " + token.getLinha() + " - Operação invalida");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case "if":
                    case "for":
                    case "while":
                    case "read":
                    case "write":
                        teste = false;
                        comandos();
                        corpo_funcao();
                        break;
                    case "function":
                        teste = false;
                        chama_funcao();
                        corpo_funcao();
                        break;
                    case "++":
                    case "--":
                        teste = false;
                        atribuicao();
                        corpo_funcao();
                        break;
                    case "}":
                        teste = false;
                        proximo_token();
                        finaliza_funcao();
                        break;
                    default:
                        if (token.getTipo().equals("Identificador")) {
                            teste = false;
                            atribuicao();
                            corpo_funcao();
                            break;
                        } else {
                            proximo_token();
                        }

                }
            }
        }
    }

    public void chama_funcao() {
        if (token.getLexema().equals("function")) {
            proximo_token();
            if (token.getTipo().equals("Identificador")) {
                proximo_token();
                if (token.getLexema().equals("(")) {
                    proximo_token();
                    parametro_chamada_funcao();
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou (");
                    aux = ("Linha: " + token.getLinha() + " - Faltou (");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case "if":
                            case "for":
                            case "while":
                            case "read":
                            case "write":
                                teste = false;
                                comandos();
                                corpo_funcao();
                                break;
                            case "function":
                                teste = false;
                                chama_funcao();
                                corpo_funcao();
                                break;
                            case "++":
                            case "--":
                                teste = false;
                                atribuicao();
                                corpo_funcao();
                                break;
                            case "return":
                                teste = false;
                                proximo_token();
                                finaliza_funcao();
                                break;
                            default:
                                if (token.getTipo().equals("Identificador")) {
                                    teste = false;
                                    atribuicao();
                                    corpo_funcao();
                                    break;
                                } else {
                                    proximo_token();
                                }

                        }
                    }
                }
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou nome da função");
                aux = ("Linha: " + token.getLinha() + " - Faltou nome da função");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "if":
                        case "for":
                        case "while":
                        case "read":
                        case "write":
                            teste = false;
                            comandos();
                            corpo_funcao();
                            break;
                        case "function":
                            teste = false;
                            chama_funcao();
                            corpo_funcao();
                            break;
                        case "++":
                        case "--":
                            teste = false;
                            atribuicao();
                            corpo_funcao();
                            break;
                        case "return":
                            teste = false;
                            proximo_token();
                            finaliza_funcao();
                            break;
                        default:
                            if (token.getTipo().equals("Identificador")) {
                                teste = false;
                                atribuicao();
                                corpo_funcao();
                                break;
                            } else {
                                proximo_token();
                            }

                    }
                }
            }
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou function");
            aux = ("Linha: " + token.getLinha() + " - Faltou function");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case "if":
                    case "for":
                    case "while":
                    case "read":
                    case "write":
                        teste = false;
                        comandos();
                        corpo_funcao();
                        break;
                    case "function":
                        teste = false;
                        chama_funcao();
                        corpo_funcao();
                        break;
                    case "++":
                    case "--":
                        teste = false;
                        atribuicao();
                        corpo_funcao();
                        break;
                    case "return":
                        teste = false;
                        proximo_token();
                        finaliza_funcao();
                        break;
                    default:
                        if (token.getTipo().equals("Identificador")) {
                            teste = false;
                            atribuicao();
                            corpo_funcao();
                            break;
                        } else {
                            proximo_token();
                        }

                }
            }
        }
    }

    public void parametro_chamada_funcao() {
        if (token.getLexema().equals(")")) {
            proximo_token();
            if (token.getLexema().equals(";")) {
                proximo_token();
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou ;");
                aux = ("Linha: " + token.getLinha() + " - Faltou ;");
                listaErro.add(aux);
            }
        } else {
            parametro_chamada_funcao_2();
        }
    }

    public void parametro_chamada_funcao_2() {
        if (token.getTipo().equals("Identificador")) {
            identificador_vetor_registro();
            parametro_chamada_funcao_3();
        } else if (token.getTipo().equals("Numero") || token.getTipo().equals("Numero real") || token.getTipo().equals("Caracter") || token.getTipo().equals("String") || token.getLexema().equals("true") || token.getLexema().equals("false")) {
            valor();
            parametro_chamada_funcao_3();
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Erro no parametro da função");
            aux = ("Linha: " + token.getLinha() + " - Erro nos parametros da função");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case ";":
                        teste = false;
                        proximo_token();
                        break;
                    case "if":
                    case "for":
                    case "while":
                    case "write":
                    case "read":
                    case "function":
                    case "return":
                        teste = false;
                        break;
                    default:
                        if (token.getTipo().equals("Identificador")) {
                            teste = false;
                            corpo_main();
                        } else {
                            proximo_token();
                        }
                }
            }
        }
    }

    public void parametro_chamada_funcao_3() {
        switch (token.getLexema()) {
            case ")":
                proximo_token();
                if (token.getLexema().equals(";")) {
                    proximo_token();
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou ;");
                    aux = ("Linha: " + token.getLinha() + " - Faltou ;");
                    listaErro.add(aux);
                }
                break;
            case ",":
                proximo_token();
                parametro_chamada_funcao_2();
                break;
            default:
                System.out.println("Linha: " + token.getLinha() + " - Faltou ,");
                aux = ("Linha: " + token.getLinha() + " - Faltou ,");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case ";":
                            teste = false;
                            proximo_token();
                            break;
                        case "if":
                        case "for":
                        case "while":
                        case "write":
                        case "read":
                        case "function":
                        case "return":
                            teste = false;
                            break;
                        default:
                            if (token.getTipo().equals("Identificador")) {
                                teste = false;
                                corpo_main();
                            } else {
                                proximo_token();
                            }
                    }
                }
                break;
        }
    }

    // VARIAVEL LOCAL DE UMA FUNCAO
    private void declara_var_local() {
        //System.out.println("token:"+this.token.getLexema());
        if (token.getLexema().equals("var")) {
            proximo_token();
            ///System.out.println("token:"+this.token);
            if (token.getLexema().equals("{")) {
                /// System.out.println(token.getLexema().equals("{"));
                proximo_token();
                bloco_variaveis_locais();
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou {");
                aux = ("Linha: " + token.getLinha() + " - Faltou {");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "}":
                            teste = false;
                            proximo_token();
                            corpo_funcao();
                            break;
                        case "if":
                        case "for":
                        case "while":
                        case "write":
                        case "read":
                        case "function":
                        case "return":
                            teste = false;
                            corpo_funcao();
                            break;
                        default:
                            if (token.getTipo().equals("Identificador")) {
                                teste = false;
                                corpo_main();
                            } else {
                                proximo_token();
                            }
                    }
                }
            }
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou var");
            aux = ("Linha: " + token.getLinha() + " - Faltou var");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case "{":
                        teste = false;
                        proximo_token();
                        bloco_variaveis_locais();
                        break;
                    case "if":
                    case "for":
                    case "while":
                    case "write":
                    case "read":
                    case "function":
                        teste = false;
                        corpo_funcao();
                        break;
                    default:
                        if (token.getTipo().equals("Identificador")) {
                            teste = false;
                            corpo_funcao();
                        } else {
                            proximo_token();
                        }
                }
            }
        }
    }

    public void bloco_variaveis_locais() {
        if (token.getTipo().equals("Identificador") || token.getLexema().equals("integer") || token.getLexema().equals("real") || token.getLexema().equals("boolean") || token.getLexema().equals("string") || token.getLexema().equals("char")) {
            tipo_extendido();
            if (token.getTipo().equals("Identificador")) {
                identificador();
                bloco_variaveis_locais();
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou nome da variavel");
                aux = ("Linha: " + token.getLinha() + " - Faltou nome da variavel");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case ";":
                            teste = false;
                            proximo_token();
                            bloco_variaveis_locais();
                            break;
                        case "}":
                            teste = false;
                            proximo_token();
                            corpo_funcao();
                            break;
                        case "if":
                        case "for":
                        case "while":
                        case "write":
                        case "read":
                        case "function":
                            teste = false;
                            corpo_funcao();
                            break;
                        default:
                            if (token.getTipo().equals("Identificador")) {
                                teste = false;
                                corpo_funcao();
                            } else {
                                proximo_token();
                            }
                    }
                }
            }
        } else if (token.getLexema().equals("}")) {
            proximo_token();
            corpo_funcao();
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou }");
            aux = ("Linha: " + token.getLinha() + " - Faltou }");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case ";":
                        teste = false;
                        proximo_token();
                        corpo_funcao();
                        break;
                    case "}":
                        teste = false;
                        proximo_token();
                        break;

                    default:
                        proximo_token();
                }
            }
        }
    }

    public void bloco_constante() {
        switch (token.getLexema()) {
            case "integer":
            case "real":
            case "boolean":
            case "string":
            case "char":
                Constante cte = new Constante();
                cte.setTipo(token.getLexema());

                tipo_primitivo();
                if (token.getTipo().equals("Identificador")) {
                    if (constante.containsKey(token.getLexema())) {
                        
                        listaErro.add("Constante já declarada. Linha:"+token.getLinha());
                        
                    } else {
                        cte.setIdentificador(token.getLexema());
                        constante.put(token.getLexema(), cte);

                    }

                    proximo_token();


                    if (token.getLexema().equals("=")) {
                        proximo_token();
                        valor();
                        if (token.getLexema().equals(";")) {
                            proximo_token();
                            bloco_constante();
                        } else {
                            System.out.println("Linha: " + token.getLinha() + " - Faltou ;");
                            aux = ("Linha: " + token.getLinha() + " - Faltou ;");
                            listaErro.add(aux);
                            bloco_constante();
                        }
                    } else {
                        System.out.println("Linha: " + token.getLinha() + " - Faltou o operador de atribuição");
                        aux = ("Linha: " + token.getLinha() + " - Faltou o operador de atribuição");
                        listaErro.add(aux);
                        boolean teste = true;
                        while (teste) {
                            switch (token.getLexema()) {
                                case "$":
                                    teste = false;
                                    break;
                                case "}":
                                    teste = false;
                                    proximo_token();
                                    declara_var_global();
                                    break;
                                case "var":
                                    teste = false;
                                    declara_var_global();
                                    break;
                                case "type":
                                    teste = false;
                                    declara_registro();
                                    break;
                                case "function":
                                    teste = false;
                                    declara_var_global();
                                    break;
                                case "main":
                                    teste = false;
                                    declara_var_global();
                                    break;
                                case "integer":
                                case "real":
                                case "boolean":
                                case "string":
                                case "char":
                                    teste = false;
                                    bloco_constante();
                                    break;
                                default:
                                    proximo_token();
                            }
                        }
                    }
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou nome da variavel");
                    aux = ("Linha: " + token.getLinha() + " - Faltou nome da variavel");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case "}":
                                teste = false;
                                proximo_token();
                                declara_var_global();
                                break;
                            case "var":
                                teste = false;
                                declara_var_global();
                                break;
                            case "type":
                                teste = false;
                                declara_registro();
                                break;
                            case "function":
                                teste = false;
                                declara_var_global();
                                break;
                            case "main":
                                teste = false;
                                declara_var_global();
                                break;
                            case "integer":
                            case "real":
                            case "boolean":
                            case "string":
                            case "char":
                                teste = false;
                                bloco_constante();
                                break;
                            default:
                                proximo_token();
                        }
                    }
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case "}":
                                teste = false;
                                proximo_token();
                                declara_var_global();
                                break;
                            case "var":
                                teste = false;
                                declara_var_global();
                                break;
                            case "type":
                                teste = false;
                                declara_registro();
                                break;
                            case "function":
                                teste = false;
                                declara_var_global();
                                break;
                            case "main":
                                teste = false;
                                declara_var_global();
                                break;
                            case "integer":
                            case "real":
                            case "boolean":
                            case "string":
                            case "char":
                                teste = false;
                                bloco_constante();
                                break;
                            default:
                                proximo_token();
                        }
                    }
                }
                break;
            case "}":
                proximo_token();
                declara_var_global();
                break;
            default:
                System.out.println("Linha: " + token.getLinha() + " - Faltou }");
                aux = ("Linha: " + token.getLinha() + " - Faltou }");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "var":
                            teste = false;
                            declara_var_global();
                            break;
                        case "type":
                            teste = false;
                            declara_registro();
                            break;
                        case "function":
                            teste = false;
                            declara_var_global();
                            break;
                        case "main":
                            teste = false;
                            declara_var_global();
                            break;
                        case "integer":
                        case "real":
                        case "boolean":
                        case "string":
                        case "char":
                            teste = false;
                            bloco_constante();
                            break;
                        default:
                            proximo_token();
                    }
                }
                break;
        }
    }

    public void tipo_primitivo() {
        if (token.getLexema().equals("integer") || token.getLexema().equals("real") || token.getLexema().equals("boolean") || token.getLexema().equals("string") || token.getLexema().equals("char")) {
            proximo_token();
        } else {
        }
    }

    public void valor() {
        if (token.getTipo().equals("Numero real") || token.getTipo().equals("Numero") || token.getTipo().equals("Caracter") || token.getTipo().equals("String")) {
            proximo_token();
        } else if (token.getLexema().equals("true") || token.getLexema().equals("false")) {
            proximo_token();
        } else {
        }
    }

    public void declara_var_global() {
        //System.out.println("token:"+this.token.getLexema());
        if (token.getLexema().equals("var")) {
            proximo_token();
            ///System.out.println("token:"+this.token);
            if (token.getLexema().equals("{")) {
                /// System.out.println(token.getLexema().equals("{"));
                proximo_token();
                bloco_variaveis();
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou {");
                aux = ("Linha: " + token.getLinha() + " - Faltou {");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "}":
                            teste = false;
                            proximo_token();
                            apos_variaveis();
                            break;
                        case "type":
                            teste = false;
                            declara_registro();
                            break;
                        case "function":
                            teste = false;
                            declara_funcao();
                            break;
                        case "main":
                            teste = false;
                            declara_main();
                            break;
                        case "integer":
                        case "real":
                        case "boolean":
                        case "string":
                        case "char":
                            teste = false;
                            bloco_variaveis();
                            break;
                        default:
                            proximo_token();
                    }
                }
            }
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou var");
            aux = ("Linha: " + token.getLinha() + " - Faltou var");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case "{":
                        teste = false;
                        proximo_token();
                        bloco_variaveis();
                        break;
                    case "}":
                        teste = false;
                        proximo_token();
                        apos_variaveis();
                        break;
                    case "type":
                        teste = false;
                        declara_registro();
                        break;
                    case "function":
                        teste = false;
                        declara_funcao();
                        break;
                    case "main":
                        teste = false;
                        declara_main();
                        break;
                    case "integer":
                    case "real":
                    case "boolean":
                    case "string":
                    case "char":
                        teste = false;
                        bloco_variaveis();
                        break;
                    default:
                        proximo_token();
                }
            }
        }
    }

    public void bloco_variaveis() {
        switch (token.getLexema()) {
            case "integer":
            case "real":
            case "boolean":
            case "string":
            case "char":
                Variavel var = new Variavel();
                var.setTipo(token.getLexema());
                proximo_token();
                if (token.getTipo().equals("Identificador")) {
                    var.setIdentificador(token.getLexema());
                    proximo_token();
                    switch (token.getLexema()) {
                        case ";":
                            proximo_token();
                            if (!constante.containsKey(var.getIdentificador())) {
                                varGlobais.put(var.getIdentificador(), var);
                            }
                            bloco_variaveis();
                        case "[":
                            proximo_token();
                            indice_vetor_matriz();
                            if (token.getLexema().equals("]")) {
                                proximo_token();
                                var.setVetor(true);
                                switch (token.getLexema()) {
                                    case ";":
                                        proximo_token();
                                        if (!constante.containsKey(var.getIdentificador())) {
                                            varGlobais.put(var.getIdentificador(), var);
                                        }
                                        bloco_variaveis();
                                    case "[":
                                        proximo_token();
                                        indice_vetor_matriz();
                                        if (token.getLexema().equals("]")) {
                                            proximo_token();
                                            var.setMatriz(true);
                                            if (token.getLexema().equals(";")) {
                                                proximo_token();
                                                if (!constante.containsKey(var.getIdentificador())) {
                                                    varGlobais.put(var.getIdentificador(), var);
                                                }
                                                bloco_variaveis();
                                            }
                                        }
                                }
                            }
                    }
                }
                break;
            case "}":
                proximo_token();
                apos_variaveis();
                break;
        }
    }

    public void atribuicao_for() {
        identificador_vetor_registro();
        switch (token.getLexema()) {
            case "=":
                proximo_token();
                posterior();
                break;
            case "++":
                proximo_token();
                identificador_vetor_registro();
                break;
            case "--":
                proximo_token();
                identificador_vetor_registro();
                break;
            default:
                System.out.println("Linha: " + token.getLinha() + " - Faltou Atribuição");
                aux = ("Linha: " + token.getLinha() + " - Faltou Atribuição");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "{":
                            teste = false;
                            proximo_token();
                            corpo_main();
                            break;
                        case "if":
                        case "for":
                        case "while":
                        case "read":
                        case "write":
                            teste = false;
                            comandos();
                            corpo_main();
                            break;
                        case "function":
                            teste = false;
                            chama_funcao();
                            corpo_main();
                            break;
                        case "++":
                        case "--":
                            teste = false;
                            atribuicao();
                            corpo_main();
                            break;
                        case "return":
                            teste = false;
                            proximo_token();
                            finaliza_funcao();
                            break;
                        default:
                            if (token.getTipo().equals("Identificador")) {
                                teste = false;
                                atribuicao();
                                corpo_main();
                                break;
                            } else {
                                proximo_token();
                            }
                    }
                }
        }
    }

    public void atribuicao() {
        identificador_vetor_registro();
        switch (token.getLexema()) {
            case "=":
                proximo_token();
                posterior();
                if (token.getLexema().equals(";")) {
                    proximo_token();
                }
                break;
            case "++":
                proximo_token();
                identificador_vetor_registro();
                if (token.getLexema().equals(";")) {
                    proximo_token();
                }
                break;
            case "--":
                proximo_token();
                identificador_vetor_registro();
                if (token.getLexema().equals(";")) {
                    proximo_token();
                }
                break;
            default:
                System.out.println("Linha: " + token.getLinha() + " - Faltou Atribuição");
                aux = ("Linha: " + token.getLinha() + " - Faltou Atribuição");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "if":
                        case "for":
                        case "while":
                        case "read":
                        case "write":
                            teste = false;
                            comandos();
                            corpo_funcao();
                            break;
                        case "function":
                            teste = false;
                            chama_funcao();
                            corpo_funcao();
                            break;
                        case "++":
                        case "--":
                            teste = false;
                            atribuicao();
                            corpo_funcao();
                            break;
                        case "return":
                            teste = false;
                            proximo_token();
                            finaliza_funcao();
                            break;
                        default:
                            if (token.getTipo().equals("Identificador")) {
                                teste = false;
                                atribuicao();
                                corpo_funcao();
                                break;
                            } else {
                                proximo_token();
                            }

                    }
                }
                break;
        }
    }

    public void posterior() {
        if (token.getTipo().equals("Numero real") || token.getTipo().equals("Numero") || token.getTipo().equals("Identificador")) {
            expressao_aritmetica();
        } else if (token.getLexema().equals("function")) {
            chama_funcao();
        } else if (token.getLexema().equals("true")) {
            proximo_token();
        } else if (token.getLexema().equals("false")) {
            proximo_token();
        } else if (token.getTipo().equals("Caracter")) {
            proximo_token();
        } else if (token.getTipo().equals("String")) {
            proximo_token();
        } else {

            aux = ("Linha: " + token.getLinha() + " - Faltou termo posterior");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case ";":
                        teste = false;
                        proximo_token();
                        break;
                    case "{":
                        teste = false;
                        declara_constante();
                        break;
                    case ")":
                        teste = false;
                        declara_constante();
                        break;
                    case "if":
                        teste = false;
                        declara_constante();
                        break;
                    case "else":
                        teste = false;
                        declara_constante();
                        break;
                    case "for":
                        teste = false;
                        declara_constante();
                        break;
                    case "while":
                        teste = false;
                        declara_constante();
                        break;


                    default:
                        proximo_token();
                }
            }


        }
    }
    /// <valor_expressao_aritmetica>::="numero_inteiro"|"numero_real"|<identificador_vetor_registro> 

    public void valor_expressao_aritmetica() {
        switch (token.getTipo()) {
            case "Numero real":
                proximo_token();
                break;
            case "Numero":
                proximo_token();
                break;
            case "Identificador":
                proximo_token();
                break;
            default:
                break;
        }
    }

    public void termo() {
        valor_expressao_aritmetica();
        termo_extendido();
    }

    public void termo_extendido() {
        switch (token.getLexema()) {
            case "*":
                proximo_token();
                valor_expressao_aritmetica();
                termo_extendido();
                break;
            case "/":
                valor_expressao_aritmetica();
                termo_extendido();
                break;
            default:
                break;
        }
    }

    public void expressao_aritmetica() {
        termo();
        expressao_aritmetica_extendida();
    }

    public void expressao_aritmetica_extendida() {
        switch (token.getLexema()) {
            case "+":
                proximo_token();
                termo();
                expressao_aritmetica_extendida();
                break;
            case "-":
                proximo_token();
                termo();
                expressao_aritmetica_extendida();
                break;
        }
    }

    public void expressao_relacional() {
        expressao();
        operador_relacional();
        expressao();
    }

    public void expressao() {
        switch (token.getTipo()) {
            case "Numero real":
            case "Numero":
            case "Identificador":
                proximo_token();
                break;
            case "String":
                proximo_token();
                break;
            case "Caracter":
                expressao_aritmetica();
                break;
            default:
                break;
        }
    }

    public void operador_relacional() {
        if (token.getLexema().equals("==") || token.getLexema().equals("!=") || token.getLexema().equals("<") || token.getLexema().equals(">") || token.getLexema().equals("<=") || token.getLexema().equals(">=")) {
            proximo_token();
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Erro no operador relacional");
            aux = ("Linha: " + token.getLinha() + " - Erro no operador relacional");
            listaErro.add(aux);
        }
    }

    public void expressao_logica() {
        expressao_relacional();
        continuacao_logica();
    }

    public void continuacao_logica() {
        if (token.getTipo().equals("Operador lógico")) {
            proximo_token();
            expressao_relacional();
            continuacao_logica();
        }
    }
    // <escreve_tela>::="write""("<parametro_write>

    public void escreve_tela() {
        if (token.getLexema().equals("(")) {
            proximo_token();
            parametro_write();
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou (");
            aux = ("Linha: " + token.getLinha() + " - Faltou (");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case ";":
                        teste = false;
                        break;
                    case "(":
                        teste = false;
                        proximo_token();
                        parametro_write();
                        break;
                    case ")":
                        teste = false;
                        proximo_token();
                        break;
                    default:
                        proximo_token();

                }
            }
        }
    }

//<parametro_write>::=<expressao_aritmetica><complemento_write>|"cadeia_constante"<complemento_write>|"caracter_constante"<complemento_write>
    public void parametro_write() {
        switch (token.getTipo()) {
            case "cadeia_constante":
                proximo_token();
                complemento_write();
                break;
            case "caracter_constante":
                proximo_token();
                complemento_write();
                break;
            default:
                proximo_token();
                expressao_aritmetica();
                complemento_write();
                break;
        }
    }

//<complemento_write>::=","<parametro_write>|")"";"         
    private void complemento_write() {
        switch (token.getLexema()) {
            case ",":
                proximo_token();
                parametro_write();
                break;
            case ")":
                proximo_token();
                if (token.getLexema().equals(";")) {
                    proximo_token();
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou ;");
                    aux = ("Linha: " + token.getLinha() + " - Faltou ;");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case ";":
                                teste = false;
                                break;
                            default:
                                proximo_token();
                        }
                    }
                }
                break;
            default:
                System.out.println("Linha: " + token.getLinha() + " - Faltou Complemento Write");
                aux = ("Linha: " + token.getLinha() + " - Faltou Complemento Write");
                listaErro.add(aux);
                break;
        }
    }

//************* FIM DO WRITE **********************
//************ WHILE ******************************
//<comando_while>::="while""("<expressao_logica>")""{"<corpo_main>
    public void comando_while() {
        if (token.getLexema().equals("(")) {
            proximo_token();
            expressao_logica();
            if (token.getLexema().equals(")")) {
                proximo_token();
                if (token.getLexema().equals("{")) {
                    proximo_token();
                    corpo_main();
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou {");
                    aux = ("Linha: " + token.getLinha() + " - Faltou {");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case "{":
                                teste = false;
                                proximo_token();
                                corpo_main();
                                break;
                            case "(":
                                teste = false;
                                proximo_token();
                                expressao_logica();
                                break;
                            case ")":
                                teste = false;
                                proximo_token();
                                comandos();
                                break;
                            default:
                                proximo_token();

                        }
                    }

                }
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou )");
                aux = ("Linha: " + token.getLinha() + " - Faltou )");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case ")":
                            teste = false;
                            proximo_token();
                            break;
                        case "{":
                            teste = false;
                            proximo_token();
                            corpo_main();
                            break;
                        case "}":
                            teste = false;
                            proximo_token();
                            break;
                        case "(":
                            teste = false;
                            proximo_token();
                            expressao_logica();
                            break;
                        default:
                            proximo_token();
                    }
                }
            }
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou (");
            aux = ("Linha: " + token.getLinha() + " - Faltou (");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case "(":
                        teste = false;
                        proximo_token();
                        expressao_logica();
                        break;
                    case "{":
                        teste = false;
                        proximo_token();
                        corpo_main();
                        break;
                    case "}":
                        teste = false;
                        break;
                    case ")":
                        teste = false;
                        proximo_token();
                        break;
                    default:
                        proximo_token();
                }
            }
        }
    }

//****************** FIM DO WHILE *************************************
//****************** FOR **********************************************
//<comando_for>::="for""(""identificador""="<valor_for>";"<expressao_logica>";"<atribuicao_for>")"{"<corpo_main>
//<valor_for>::="numero_real"|"identificador"|"numero_inteiro"
    public void comando_for() {
        if (token.getLexema().equals("(")) {
            proximo_token();
            if (token.getTipo().equals("Identificador")) {
                proximo_token();
                if (token.getLexema().equals("=")) {
                    proximo_token();
                    valor_for();
                    if (token.getLexema().equals(";")) {
                        proximo_token();
                        expressao_logica();
                        if (token.getLexema().equals(";")) {
                            proximo_token();
                            atribuicao_for();
                            if (token.getLexema().equals(")")) {
                                proximo_token();
                                if (token.getLexema().equals("{")) {
                                    proximo_token();
                                    corpo_main();
                                } else {
                                    System.out.println("Linha: " + token.getLinha() + " - Faltou {");
                                    aux = ("Linha: " + token.getLinha() + " - Faltou {");
                                    listaErro.add(aux);
                                    boolean teste = true;
                                    while (teste) {
                                        switch (token.getLexema()) {
                                            case "$":
                                                teste = false;
                                                break;
                                            case "{":
                                                teste = false;
                                                proximo_token();
                                                corpo_main();
                                                break;
                                            case "(":
                                                teste = false;
                                                comando_for();
                                                break;
                                            case ";":
                                                teste = false;
                                                break;
                                            case "}":
                                                teste = false;
                                                proximo_token();
                                                break;
                                            default:
                                                proximo_token();
                                        }
                                    }
                                }
                            } else {
                                System.out.println("Linha: " + token.getLinha() + " - Faltou )");
                                aux = ("Linha: " + token.getLinha() + " - Faltou )");
                                listaErro.add(aux);
                                boolean teste = true;
                                while (teste) {
                                    switch (token.getLexema()) {
                                        case "$":
                                            teste = false;
                                            break;
                                        case ")":
                                            teste = false;
                                            proximo_token();
                                            break;
                                        case "}":
                                            teste = false;
                                            break;
                                        case "(":
                                            teste = false;
                                            comando_for();
                                            break;
                                        case ";":
                                            teste = false;
                                            break;
                                        default:
                                            proximo_token();
                                    }
                                }
                            }
                        } else {
                            System.out.println("Linha: " + token.getLinha() + " - Faltou ;");
                            aux = ("Linha: " + token.getLinha() + " - Faltou ;");
                            listaErro.add(aux);
                            boolean teste = true;
                            while (teste) {
                                switch (token.getLexema()) {
                                    case "$":
                                        teste = false;
                                        break;
                                    case ")":
                                        teste = false;
                                        proximo_token();
                                        break;
                                    case ";":
                                        teste = false;
                                        proximo_token();
                                        atribuicao_for();
                                        break;
                                    case "{":
                                        teste = false;
                                        proximo_token();
                                        corpo_main();
                                        break;
                                    case "++":
                                        teste = false;
                                        atribuicao_for();
                                        break;
                                    case "--":
                                        teste = false;
                                        atribuicao_for();
                                        break;
                                    case "identificador":
                                        teste = false;
                                        atribuicao_for();
                                        break;
                                    default:
                                        proximo_token();
                                }
                            }
                        }
                    } else {
                        System.out.println("Linha: " + token.getLinha() + " - Faltou ;");
                        aux = ("Linha: " + token.getLinha() + " - Faltou ;");
                        listaErro.add(aux);
                        boolean teste = true;
                        while (teste) {
                            switch (token.getLexema()) {
                                case "$":
                                    teste = false;
                                    break;
                                case ";":
                                    teste = false;
                                    proximo_token();
                                    expressao_logica();
                                    break;
                                case ")":
                                    teste = false;
                                    proximo_token();
                                    break;
                                case "{":
                                    teste = false;
                                    proximo_token();
                                    corpo_funcao();
                                    break;
                                case "}":
                                    teste = false;
                                    proximo_token();
                                    break;
                                case "cadeia_constante":
                                    teste = false;
                                    expressao();
                                    break;
                                case "caracter_constante":
                                    teste = false;
                                    expressao();
                                    break;
                                case "numero_inteiro":
                                    teste = false;
                                    valor_expressao_aritmetica();
                                    break;
                                case "numero_real":
                                    teste = false;
                                    valor_expressao_aritmetica();
                                    break;
                                case "identificador":
                                    teste = false;
                                    valor_expressao_aritmetica();
                                    break;
                                default:
                                    proximo_token();
                            }
                        }
                    }
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou =");
                    aux = ("Linha: " + token.getLinha() + " - Faltou =");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case "=":
                                teste = false;
                                proximo_token();
                                break;
                            case ")":
                                teste = false;
                                proximo_token();
                                break;
                            case "{":
                                teste = false;
                                proximo_token();
                                corpo_main();
                                break;
                            case ";":
                                teste = false;
                                proximo_token();
                                expressao_logica();
                                break;
                            case "numero_real":
                                teste = false;
                                valor_for();
                                break;
                            case "identificador":
                                teste = false;
                                valor_for();
                                break;
                            case "numero_inteiro":
                                teste = false;
                                valor_for();
                                break;
                            default:
                                proximo_token();
                        }
                    }
                }
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou Identificador");
                aux = ("Linha: " + token.getLinha() + " - Faltou Identificador");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "identificador":
                            teste = false;
                            proximo_token();
                            break;
                        case "=":
                            teste = false;
                            break;
                        case ";":
                            teste = false;
                            break;
                        case "numero_real":
                            teste = false;
                            proximo_token();
                            break;
                        case "numero_inteiro":
                            teste = false;
                            proximo_token();
                            break;
                        case ")":
                            teste = false;
                            proximo_token();
                            break;
                        case "{":
                            teste = false;
                            proximo_token();
                            corpo_main();
                            break;
                        case "}":
                            teste = false;
                            proximo_token();
                            break;
                        default:
                            proximo_token();
                    }
                }
            }
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou (");
            aux = ("Linha: " + token.getLinha() + " - Faltou (");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case "(":
                        teste = false;
                        proximo_token();
                        break;
                    case "identificador":
                        teste = false;
                        proximo_token();
                        break;
                    case "=":
                        teste = false;
                        proximo_token();
                        valor_for();
                        break;
                    case ";":
                        teste = false;
                        break;
                    case ")":
                        teste = false;
                        proximo_token();
                        break;
                    case "{":
                        teste = false;
                        proximo_token();
                        corpo_main();
                        break;
                    case "numero_real":
                        teste = false;
                        proximo_token();
                        break;
                    case "numero_inteiro":
                        teste = false;
                        proximo_token();
                        break;
                    default:
                        proximo_token();
                }
            }
        }
    }

//<valor_for>::="numero_real"|"identificador"|"numero_inteiro"
    public void valor_for() {
        switch (token.getTipo()) {
            case "Numero real":
                proximo_token();
                break;
            case "Identificador":
                proximo_token();
                break;
            case "Numero":
                proximo_token();
                break;
            default:
                System.out.println("Linha: " + token.getLinha() + " - Faltou o Valor");
                aux = ("Linha: " + token.getLinha() + " - Faltou o Valor");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "=":
                            teste = false;
                            proximo_token();
                            break;
                        case ")":
                            teste = false;
                            proximo_token();
                            break;
                        case "{":
                            teste = false;
                            proximo_token();
                            corpo_main();
                            break;
                        case ";":
                            teste = false;
                            break;
                        default:
                            proximo_token();
                    }
                }
        }
    }

    //****************** FIM DO FOR ********************
    //******************** READ ************************
    //<ler_variavel>::="read""("<parametro_read>
    public void ler_variavel() {
        if (token.getLexema().equals("(")) {
            proximo_token();
            parametro_read();
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou (");
            aux = ("Linha: " + token.getLinha() + " - Faltou (");
            listaErro.add(aux);
            parametro_read();
        }
    }
//<parametro_read>::=<identificador_vetor_registro><complemento_read>

    private void parametro_read() {
        identificador_vetor_registro();
        complemento_read();
    }

//<complemento_read>::=","<parametro_read>|")"";"
    private void complemento_read() {
        switch (token.getLexema()) {
            case ",":
                proximo_token();
                parametro_read();
                break;
            case ")":
                proximo_token();
                if (token.getTipo().equals(";")) {
                    proximo_token();
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou ;");
                    aux = ("Linha: " + token.getLinha() + " - Faltou ;");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case ";":
                                teste = false;
                                proximo_token();
                                break;
                            case "(":
                                teste = false;
                                proximo_token();
                                parametro_read();
                                break;
                            case "{":
                                teste = false;
                                break;
                            case ")":
                                teste = false;
                                proximo_token();
                                break;
                            case "identificador":
                                teste = false;
                                proximo_token();
                                parametro_read();
                                break;
                            default:
                                proximo_token();
                        }
                    }
                }
            default:
                System.out.println("Linha: " + token.getLinha() + " - Faltou complemento read");
                aux = ("Linha: " + token.getLinha() + " - Faltou complemento read");
                listaErro.add(aux);
                break;
        }
    }

    //*********************** FIM DO READ ******************
    //************************ IF *************************
    // *************IF
//<comando_if> ::= "if" "(" <expressao_logica> ")"
    public void comando_if() {
        if (token.getLexema().equals("(")) {
            proximo_token();
            expressao_logica();
            if (token.getLexema().equals(")")) {
                proximo_token();
                complemento_if();
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou )");
                aux = ("Linha: " + token.getLinha() + " - Faltou )");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case ")":
                            teste = false;
                            proximo_token();
                            break;
                        case "{":
                            teste = false;
                            proximo_token();
                            corpo_funcao();
                            break;
                        case ";":
                            teste = false;
                            break;
                        case "}":
                            teste = false;
                            proximo_token();
                            break;
                        default:
                            proximo_token();
                    }
                }
            }
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou (");
            aux = ("Linha: " + token.getLinha() + " - Faltou (");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case "(":
                        teste = false;
                        proximo_token();
                        expressao_logica();
                        break;
                    case "identificador":
                        teste = false;
                        proximo_token();
                        parametro_read();
                        break;
                    case ")":
                        teste = false;
                        proximo_token();
                        break;
                    case "{":
                        teste = false;
                        proximo_token();
                        corpo_main();
                        break;
                    default:
                        proximo_token();
                }
            }
        }
    }

    //<complemento_if> ::= "else" "{"<corpo_main>| E
    private void complemento_if() {
        if (token.getLexema().equals("else")) {
            proximo_token();
            if (token.getTipo().equals("{")) {
                proximo_token();
                corpo_main();
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou {");
                aux = ("Linha: " + token.getLinha() + " - Faltou {");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "{":
                            teste = false;
                            proximo_token();
                            corpo_main();
                            break;
                        case "(":
                            teste = false;
                            break;
                        case ";":
                            teste = false;
                            break;
                        case ")":
                            teste = false;
                            break;
                        default:
                            proximo_token();
                    }
                }
            }
        }
    }

    //******************* FIM DO IF ***********************
    //********************* REGISTRO ********************
//<declara_registro>::="type""register""identificador""{"<bloco_registro>
    public void declara_registro() {
        if (token.getLexema().equals("type")) {
            proximo_token();
            if (token.getLexema().equals("register")) {
                proximo_token();
                if (token.getTipo().equals("Identificador")) {
                    proximo_token();
                    if (token.getLexema().equals("{")) {
                        proximo_token();
                        bloco_registro();
                    } else {
                        System.out.println("Linha: " + token.getLinha() + " - Faltou {");
                        aux = ("Linha: " + token.getLinha() + " - Faltou {");
                        listaErro.add(aux);
                        boolean teste = true;
                        while (teste) {
                            switch (token.getLexema()) {
                                case "$":
                                    teste = false;
                                    break;
                                case "{":
                                    teste = false;
                                    proximo_token();
                                    bloco_registro();
                                    break;
                                case ";":
                                    teste = false;
                                    proximo_token();
                                    break;
                                case "(":
                                    teste = false;
                                    break;
                                case "}":
                                    teste = false;
                                    proximo_token();
                                    apos_variaveis();
                                    break;
                                case "integer":
                                    teste = false;
                                    bloco_registro();
                                    break;
                                case "real":
                                    teste = false;
                                    bloco_registro();
                                    break;
                                case "boolean":
                                    teste = false;
                                    bloco_registro();
                                    break;
                                case "string":
                                    teste = false;
                                    bloco_registro();
                                    break;
                                case "char":
                                    teste = false;
                                    bloco_registro();
                                    break;
                                default:
                                    proximo_token();
                            }
                        }
                    }
                } else {
                    System.out.println("Linha: " + token.getLinha() + " - Faltou Identificador");
                    aux = ("Linha: " + token.getLinha() + " - Faltou Identificador");
                    listaErro.add(aux);
                    boolean teste = true;
                    while (teste) {
                        switch (token.getLexema()) {
                            case "$":
                                teste = false;
                                break;
                            case "{":
                                teste = false;
                                proximo_token();
                                bloco_registro();
                                break;
                            case "}":
                                teste = false;
                                proximo_token();
                                apos_variaveis();
                                break;
                            case ";":
                                teste = false;
                                break;
                            case "identificador":
                                teste = false;
                                proximo_token();
                                break;
                            case "integer":
                                teste = false;
                                bloco_registro();
                                break;
                            case "real":
                                teste = false;
                                bloco_registro();
                                break;
                            case "boolean":
                                teste = false;
                                bloco_registro();
                                break;
                            case "string":
                                teste = false;
                                bloco_registro();
                                break;
                            case "char":
                                teste = false;
                                bloco_registro();
                                break;
                            default:
                                proximo_token();
                        }
                    }
                }
            } else {
                System.out.println("Linha: " + token.getLinha() + " - Faltou register");
                aux = ("Linha: " + token.getLinha() + " - Faltou register");
                listaErro.add(aux);
                boolean teste = true;
                while (teste) {
                    switch (token.getLexema()) {
                        case "$":
                            teste = false;
                            break;
                        case "(":
                            teste = false;
                            break;
                        case "{":
                            teste = false;
                            proximo_token();
                            bloco_registro();
                            break;
                        case "}":
                            teste = false;
                            proximo_token();
                            apos_variaveis();
                            break;
                        case ";":
                            teste = false;
                            break;
                        case "identificador":
                            teste = false;
                            proximo_token();
                            break;
                        case "integer":
                            teste = false;
                            bloco_registro();
                            break;
                        case "real":
                            teste = false;
                            bloco_registro();
                            break;
                        case "boolean":
                            teste = false;
                            bloco_registro();
                            break;
                        case "string":
                            teste = false;
                            bloco_registro();
                            break;
                        case "char":
                            teste = false;
                            bloco_registro();
                            break;
                        default:
                            proximo_token();
                    }
                }
            }
        } else {
            System.out.println("Linha: " + token.getLinha() + " - Faltou type");
            aux = ("Linha: " + token.getLinha() + " - Faltou type");
            listaErro.add(aux);
            boolean teste = true;
            while (teste) {
                switch (token.getLexema()) {
                    case "$":
                        teste = false;
                        break;
                    case "register":
                        teste = false;
                        proximo_token();
                        break;
                    case "(":
                        teste = false;
                        break;
                    case "{":
                        teste = false;
                        proximo_token();
                        bloco_registro();
                        break;
                    case "}":
                        teste = false;
                        proximo_token();
                        apos_variaveis();
                        break;
                    case ";":
                        teste = false;
                        break;
                    case "identificador":
                        teste = false;
                        proximo_token();
                        break;
                    case "integer":
                        teste = false;
                        bloco_registro();
                        break;
                    case "real":
                        teste = false;
                        bloco_registro();
                        break;
                    case "boolean":
                        teste = false;
                        bloco_registro();
                        break;
                    case "string":
                        teste = false;
                        bloco_registro();
                        break;
                    case "char":
                        teste = false;
                        bloco_registro();
                        break;
                    default:
                        proximo_token();
                }
            }
        }
    }
//<bloco_registro>::=<tipo_primitivo><identificador><bloco_registro>|"}"<apos_registro>

 	public void bloco_registro() {
        Registro reg = new Registro();
        
        switch (token.getLexema()) {
            case "}":
                if (registro.containsKey(token.getLexema())) {//verifica se já tem na tabela
                } else {
                    reg.setNome(token.getLexema());
                    registro.put(token.getLexema(), reg);
                }
                proximo_token();
                apos_variaveis();
                break;
            case "integer":
                reg.setTipo(token.getLexema());

                tipo_primitivo();
                identificador();
                bloco_registro();
                break;
            case "real":
                reg.setTipo(token.getLexema());
                tipo_primitivo();
                identificador();
                bloco_registro();
                break;
            case "boolean":
                reg.setTipo(token.getLexema());
                tipo_primitivo();
                identificador();
                bloco_registro();
                break;
            case "string":
                reg.setTipo(token.getLexema());
                tipo_primitivo();
                identificador();
                bloco_registro();
                break;
            case "char":
                reg.setTipo(token.getLexema());
                tipo_primitivo();
                identificador();
                bloco_registro();
                break;
            default:
                System.out.println("Linha: " + token.getLinha() + " - Faltou }");
                aux = ("Linha: " + token.getLinha() + " - Faltou }");
                listaErro.add(aux);
                break;
        }
    }
    //<apos_registro>::=<declara_registro>|<declara_funcao>|<declara_main>
    private void apos_variaveis() {
        switch (token.getLexema()) {
            case "type":
                declara_registro();
                break;
            case "function":
                declara_funcao();
                break;
            case "main":
                declara_main();
                break;
            default:
                System.out.println("Linha: " + token.getLinha() + " - Bloco não identificado");
                aux = ("Linha: " + token.getLinha() + " - Bloco não identificado");
                listaErro.add(aux);
                break;
        }
    }
}
